﻿#define _DEBUG
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Configuration;
using DTC.Models;
using DTC.BLL;
using System.Threading;
using System.Linq;
using System.Text.RegularExpressions;


namespace Common
{
    public abstract class Product
    {
        public string ModelName { get; set; }
        bool bFail = false;
        public Action<Test_Data> SaveTestDataToList;
        public static object loker = new object();
        public bool B_Fail
        {
            get { return bFail; }
            set { bFail = value; }
        }
        public List<TestItem> TestItems { get; set; }
        public Action<string> ShowMsg;
        public Action<List<TestSpan>> ShowTestSpan;
        public TestItem CurrentItem { get { return TestItems[Location]; } }
        #region GUID属性
        private string _GUID;
        public string GetGUID()
        {
            if (!string.IsNullOrEmpty(_GUID))
            {
                return _GUID;
            }
            _GUID = Guid.NewGuid().ToString();
            return _GUID;
        }
        #endregion
        private int _location;
        public int Location
        {
            get
            {
                return _location;
            }
        }
        public abstract int Test();
        public void StepLocation()
        {
            _location++;
        }
        #region 当测试失败，把该产品之后的站位设置为不测试
        public void SetFail()
        {
            for (int i = _location + 1; i < TestItems.Count; i++)
            {
                TestItems[i].IsUse = false;
            }
            bFail = true;
        }
        #endregion


        /// <summary>
        /// 从Xml获取设置列表
        /// </summary>
        /// <param name="FileName"></param>
        public Product(string FileName)
        {
            if (File.Exists(FileName) == false)
            {
                throw new Exception(string.Format("TestItems Setting File :  [{0}] is not Exist", FileName));
            }
            TestItems = ParseTestItems(FileName);
        }

        public static List<TestItem> ParseTestItems(string FileName)
        {
            List<TestItem> TestItems = new List<TestItem>();
            XmlNodeList nodes = XMLHelper.GetXmlNodeListByXpath(FileName, "TestItems");
            foreach (XmlNode item in nodes)
            {
                foreach (XmlNode xn in item.ChildNodes)
                {
                    TestItem ti = new TestItem();
                    foreach (XmlNode xn1 in xn.ChildNodes)
                    {
                        if (xn1.Name == "Name")
                        {
                            ti.ItemName = xn1.InnerText;
                        }
                        else if (xn1.Name == "Location")
                        {
                            ti.ItemLocation = int.Parse(xn1.InnerText.Trim('"'));
                        }
                        else if (xn1.Name == "Enable")
                        {
                            ti.IsUse = int.Parse(xn1.InnerText.Trim('"')) > 0 ? true : false;
                        }
                    }
                    TestItems.Add(ti);
                }
            }
            return TestItems;
        }
    }
    public class TMC01 : Product
    {
        public TMC01(string fileName)
            : base(fileName)
        {

        }
        public override int Test()
        {
            if (Location >= TestItems.Count)
            {
                LogHelper.WriteLog(typeof(Product), "测试值超出索引");
                return 0;
            }
            TestItem item = TestItems[Location];
            ShowMsg("测试项目:" + item.ItemName);
            if (item.IsUse)
            {
                ShowMsg("测试序列号:" + Location.ToString());
                ShowMsg("产品:" + GetGUID());
                ShowMsg("测试点位:" + item.ItemLocation.ToString());
                ShowMsg("测试使能状态:" + item.IsUse.ToString());
                int IOLocation = item.ItemLocation;
                bool bState = PISO730.Instance.ReadBit((ushort)IOLocation);
                bool result = Test(item.ItemName, !bState);
                if (result)
                {
                    ShowMsg("[测试结果]: [PASS]");
                    return 1;
                }
                else
                {
                    ShowMsg("[测试结果]: [FAIL]");
                    SetFail();
                    return -1;
                }
            }
            else
            {
                ShowMsg("[测试结果]: [未测试]");
                return 0;
            }
        }
        public static decimal ChangeDataToD(string strData)
        {
            decimal dData;
            if (strData.ToUpper().Contains("E"))
            {
                string[] splits = strData.Split(new char[] { 'E' });
                dData = Convert.ToDecimal(Convert.ToDouble(splits[0]) * Math.Pow(10, Convert.ToDouble(splits[1])));
            }
            else
            {
                dData = Convert.ToDecimal(strData);
            }
            return dData;
        }
        private bool Test(string TestFuncName, bool bState)
        {
            if (TestFuncName.Contains("耐压"))
            {
                ShowMsg(string.Format("[{0}结果]:{1}", TestFuncName, (bState ? "失败" : "成功")));
                string strIndex = TestFuncName.Substring(TestFuncName.Length - 2, 1);
                int index = int.Parse(strIndex);
                if (bState)
                {
                    CountManager.nyFailCount[index]++;
                }
                CountManager.nyTotalCount[index]++;
                List<TestSpan> tss = new List<TestSpan>();
                TestSpan ts = new TestSpan();
                ts.测试结果 = (bState ? "FAIL" : "PASS");
                ts.测试项目 = TestFuncName.Trim('"');
                ts.测试值 = (bState ? "FAIL" : "PASS");
                ts.最大值 = "NA";
                ts.最小值 = "NA";
                ts.不良数量 = CountManager.nyFailCount[index].ToString();
                ts.不良率 = (CountManager.nyFailCount[index] * 1.0 / CountManager.nyTotalCount[index]).ToString("P");
                tss.Add(ts);
                SaveTestDataToList(new Test_Data() { 
                    GUID = GetGUID(), 
                    Max = ts.最大值, 
                    Min = ts.最小值, 
                    Model = ModelName ,
                    Value1=ts.测试值,
                    Name=ts.测试项目,
                    Result=ts.测试结果,
                    Value2="",
                    AddTime=DateTime.Now});
                ShowTestSpan(tss);
                return bState ? false : true;
            }
            else if (TestFuncName.Contains("漏感"))
            {
                ShowMsg(string.Format("准备开始{0}测试", TestFuncName));
                string lgpath = ConfigurationManager.AppSettings["LGPath"];
                string filename = string.Format(@"{0}\BinComp.txt", lgpath);
                LGParser lgps = new LGParser(filename);
                List<string> values = lgps.getLastRecord();
                ShowMsg(string.Format("[{0}资料]|", TestFuncName) + string.Join(",", values.ToArray()));
                bool bLgResult = values.Contains("PASS");
                //string strIndex = TestFuncName.Substring(TestFuncName.Length - 2, 1);
                //int index = int.Parse(strIndex);
                var m=Regex.Match(TestFuncName,@"\d{1,3}");
                int index=0;
                if(m.Success)
                {
                     index=int.Parse( m.Value);
                }
                if (!bLgResult)
                {
                    CountManager.lgFailCount[index]++;
                }
                CountManager.lgTotalCount[index]++;
                List<TestSpan> tss = new List<TestSpan>();
                TestSpan ts = new TestSpan();
                ts.测试项目 = TestFuncName.Trim('"');
                ts.最大值 = (decimal.Parse(values[2].Remove(values[2].Length - 2)) * 1000).ToString("f3");
                ts.最小值 = (decimal.Parse(values[1].Remove(values[1].Length - 2)) * 1000).ToString("f3");
                ts.测试值 = (ChangeDataToD(values[3]) * 1000000000).ToString("f3");
                ts.测试结果 = values[5];
                ts.不良数量 = CountManager.lgFailCount[index].ToString();
                ts.不良率 = (CountManager.lgFailCount[index] * 1.0 / CountManager.lgTotalCount[index]).ToString("P");
                tss.Add(ts);
                SaveTestDataToList(new Test_Data()
                {
                    GUID = GetGUID(),
                    Max = ts.最大值,
                    Min = ts.最小值,
                    Model = ModelName,
                    Value1 = ts.测试值,
                    Name = ts.测试项目,
                    Result = ts.测试结果,
                    Value2 = "",
                    AddTime =DateTime.Now
                });
                ShowTestSpan(tss);
                if (bLgResult)
                {
                    ShowMsg(string.Format("[{0}结果]:成功", TestFuncName));
                    return true;
                }
                else
                {
                    ShowMsg(string.Format("[{0}结果]:失败", TestFuncName));
                    return false;
                }
            }
            else if (TestFuncName.Contains("综测"))
            {
                ShowMsg("开始解析综测数据");
                System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                sw.Start();
                string AtrCom = ConfigurationManager.AppSettings["AtrCom"];
                string AtrPath = ConfigurationManager.AppSettings["AtrPath"];
                string filePath;
                if (!AtrParser.GetAtrFileName(AtrPath, out filePath, DateTime.Now))
                {
                    if (AtrParser.GetAtrFileName(AtrPath, out filePath, DateTime.Now.AddDays(-1)) == false)
                    {
                        ShowMsg("综测文件不存在");
                        return false;
                    }       
                }
                AtrParser atr = new AtrParser(filePath);
                List<TestSpan> spans = new List<TestSpan>();
                bool result = atr.getTestSpans(ref spans);
                foreach (TestSpan ts in spans)
                {
                    if (ts.测试项目.Contains("LS"))
                    {
                        int Multiple = int.Parse(ConfigurationManager.AppSettings["LS_Multiple"]);
                        string temp = Math.Round(ChangeDataToD(ts.测试值) * Multiple, 3).ToString();
                        ts.测试值 = temp;
                        temp = (Math.Round(ChangeDataToD(ts.最大值) * Multiple, 3)).ToString();
                        ts.最大值 = temp;
                        temp = (Math.Round(ChangeDataToD(ts.最小值) * Multiple, 3)).ToString();
                        ts.最小值 = temp;
                    }
                    else if (ts.测试项目.Contains("TR"))
                    {
                        ts.测试项目 = DisplaySettings.instance.getSubName2(ts.测试项目);
                        ts.测试值 = (float.Parse(ts.测试值)).ToString("f3");
                        ts.最大值 = (float.Parse(ts.最大值)).ToString("f3");
                        ts.最小值 = (float.Parse(ts.最小值)).ToString("f3");
                    }
                    else if (ts.测试项目.Contains("R"))
                    {
                        float Multiple = float.Parse(ConfigurationManager.AppSettings["R_Multiple"]);
                        ts.测试值 = (float.Parse(ts.测试值) * Multiple).ToString("f3");
                        ts.最大值 = (float.Parse(ts.最大值) * Multiple).ToString("f3");
                        ts.最小值 = (float.Parse(ts.最小值) * Multiple).ToString("f3");
                    }
                    else if (ts.测试项目.Contains("LVOC"))
                    {
                        int Mutiple = int.Parse(ConfigurationManager.AppSettings["LVOC_Multiple"]);
                        string temp = Math.Round((ChangeDataToD(ts.测试值) * Mutiple), 3).ToString();
                        ts.测试值 = temp;
                        temp = (Math.Round(ChangeDataToD(ts.最大值) * Mutiple, 3)).ToString();
                        ts.最大值 = temp;
                        temp = (Math.Round((ChangeDataToD(ts.最小值) * Mutiple), 3)).ToString();
                        ts.最小值 = temp;
                    }
                    SaveTestDataToList(new Test_Data()
                    {
                        GUID = GetGUID(),
                        Max = ts.最大值,
                        Min = ts.最小值,
                        Model = ModelName,
                        Value1 = ts.测试值,
                        Name = ts.测试项目,
                        Result = ts.测试结果,
                        Value2 = "",
                        AddTime=DateTime.Now
                    });   
                }
                spans.Reverse();
                ShowTestSpan(spans);
                sw.Stop();

                LogHelper.WriteLog(typeof(Product), string.Format("读取ATR文件用的时间 {0} ms", sw.ElapsedMilliseconds));
                if (!result)
                {
                    ShowMsg("[综测结果]:失败");
                    SetFail();
                    return false;
                }
                else
                {
                    ShowMsg("[综测结果]:成功");
                    return true;
                }
                //}
                //else
                //{
                //    ShowMsg("[综测错误]:综测端口是低电平,流程混乱了");
                //    return false;
                //}
            }
            else if (TestFuncName.Contains("图像"))
            {
                //if (bState)
                //{
                ShowMsg("图像端口是高电平,开始测试图像数据");
                int iStart = Environment.TickCount;
                string CCDPath = ConfigurationManager.AppSettings["ccdPath"];
                string filePath = string.Format(@"{0}\{1}.csv", CCDPath, DateTime.Now.ToString("yyyyMMdd"));
                CCDParser cpr = new CCDParser(filePath);
                List<TestSpan> spns = new List<TestSpan>();
                List<string> values = new List<string>();
                bool ret = cpr.getResult(ref spns, ref values);
                LogHelper.WriteLog(typeof(Product), string.Format("读取图像文件用时{0}ms", Environment.TickCount - iStart));
                foreach (TestSpan ts in spns)
                {
                    // DTC.BLL.Test_DatasManager.InsertTestData(sp, ModelName, GetGUID(), values.ToArray());
                    SaveTestDataToList(new Test_Data()
                    {
                        GUID = GetGUID(),
                        Max = ts.最大值,
                        Min = ts.最小值,
                        Model = ModelName,
                        Value1 = ts.测试值,
                        Name = ts.测试项目,
                        Result = ts.测试结果,
                        Value2 =string.Join(",",values.ToArray()),
                         AddTime=DateTime.Now
                    });   
                }
                if (ret)
                {
                    ShowMsg("[图像结果]:成功");
                    ShowTestSpan(spns);
                    return true;
                }
                else
                {
                    ShowMsg("[图像结果]:失败");
                    ShowTestSpan(spns);
                    return false;
                }
                //}
                //else
                //{
                //    ShowMsg("[图像Error]:图像端口是低电平,流程混乱了");
                //    return false;
                //}
            }
            else if (TestFuncName.Contains("空站"))
            {
                return true;
            }        
            else
            {
                ShowMsg("[Error]:没有这个测试项目，请检查配置文件");
                return false;
            }
        }

        private void InsertTsData(object ts_)
        {
            lock (loker)
            {
                try
                {
                    TestSpan ts = ts_ as TestSpan;
                    DTC.BLL.Test_DatasManager.InsertTestData(ts, ModelName, GetGUID(), new string[] { "" });
                }
                catch (Exception ex)
                {
                    LogHelper.WriteLog(typeof(Product), ex);
                }
            }
        }
        private void InsertTsData_t(TestSpan ts)
        {
            Thread trd = new Thread(InsertTsData);
            //      trd.IsBackground = true;
            trd.Start(ts);
        }

        private void AtrShowAndSave(object para)
        {
            lock (loker)
            {
                try
                {
                    List<TestSpan> spans = para as List<TestSpan>;
                    foreach (var ts in spans)
                        DTC.BLL.Test_DatasManager.InsertTestData(ts, ModelName, GetGUID(), "综测");
                }
                catch (Exception ex)
                {
                    LogHelper.WriteLog(typeof(Product), ex);
                }
            }
        }
    }
}
